#ifndef POLYMESHVIEW_HPP
#define POLYMESHVIEW_HPP
#include "Mesh.hpp"
#include "PolyMesh.hpp"
#include <set>
#include <boost/bimap.hpp>
#include <boost/bimap/list_of.hpp>
#include <boost/bimap/unordered_set_of.hpp>

// Converts/maintains a polyhedral mesh to a triangle mesh for drawing
class PolyMeshView
{
   public:
      //PolyMeshView(PolyMesh* aPolyMesh);
      PolyMeshView(VertexBuffer& aVerts,
                   PolyBuffer&   aPolys);

      void Reset(VertexBuffer& aVerts,
                 PolyBuffer&   aPolys);
      //PolyMeshView(PolyAccessor*   aPolys,
      //             VertexAccessor* aVerts);

      void PolyDeleted(int aIndex);
      
      void PolyAdded();
      
      void VertexAdded();

      void PolyMove(int aOldIndex,
                    int aNewIndex);

      Mesh& GetMesh() { return mMesh; }
      
      void BuildMesh();

      void SetShownVertices(const std::vector<int>& aVerts);
      void RemoveShownVertices(const std::vector<int>& aVerts);
      void AddShownVertices(const std::vector<int>& aVerts);
      void SetPolyScaling(float aScaling) { mPolyScaling = aScaling; }
      void SetShownMaterialList(std::vector<int> aMaterials)
      {
         mShownMaterials.clear();
         mShownMaterials.insert(aMaterials.begin(), aMaterials.end());
      }
      void UseMaterialList(bool aUseMaterials) { mUseMaterialList = aUseMaterials; }
   private:
      void UpdateShownVertices();
      bool ShowPoly(Polyhedron& aPoly,
                    int         aSubdivisionLevel,
                    int         aPolyIndex);


      void GetUsedPolys(std::vector<int>& aUsedPolys);

      void BuildScaledMesh();

      //PolyMesh*   mPolyMesh;
      VertexBuffer   mVerts;
      PolyBuffer     polys;
      int         mSubdivisionLevel;
      Mesh        mMesh;

      std::vector<int>  mShownVertexList;

      std::vector<int>  mShownPolyList;
      float       mPolyScaling;
      bool        mUseCuttingPlane;
      Vec3        mCuttingPlanePoint;
      Vec3        mCuttingPlaneNormal;
      typedef std::set<Polyhedron::FaceVerts> FaceSet;

      std::set<int>  mShownMaterials;
      bool           mUseMaterialList;

      void TesseleatePoly(Polyhedron& aPoly, FaceSet& aShownFaces);
      void TesselatePolyScaled(Polyhedron& aPoly);

      struct FaceInfo
      {
         int mFaceIndex;
         int mFaceCount;
      };
      
      typedef boost::bimap<boost::bimaps::unordered_set_of<int>, boost::bimaps::unordered_set_of<int>, boost::bimaps::list_of_relation >  VertexLinkMap;
      typedef VertexLinkMap::value_type VertexLink;
      VertexLinkMap mVertexLinks;
};

#endif
